package org.jeecg.modules.wxuser.service.impl;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.WxMaUserService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import me.chanjar.weixin.common.error.WxErrorException;
import org.jeecg.com.util.ThirdSessionHolder;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.TenantContextHolder;
import org.jeecg.modules.mall.entity.MallUserInfo;
import org.jeecg.modules.wxuser.dto.LoginDto;
import org.jeecg.modules.wxuser.dto.WxOpenDataDto;
import org.jeecg.modules.wxuser.dto.ThirdSession;
import org.jeecg.modules.mall.entity.WxAppConfig;
import org.jeecg.modules.wxuser.entity.WxUser;
import org.jeecg.modules.wxuser.mapper.UserInfoMapper;
import org.jeecg.modules.wxuser.service.IUserInfoService;
import org.jeecg.modules.mall.service.IWxAppConfigService;
import org.jeecg.modules.wxuser.service.IWxUserService;
import org.jeecg.modules.mall.ma.WxMaInRedisConfigStorage;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.UUID;

/**
 * @Description: user_info
 * @Author: jeecg-boot
 * @Date:   2023-04-25
 * @Version: V1.0
 */
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, MallUserInfo> implements IUserInfoService {
@Resource
private IWxAppConfigService wxAppConfigService;
    @Resource
    private  RedisTemplate redisTemplate;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private IWxUserService wxUserService;

    /**
     * wx.login登陆成功之后发送请求，后端登录
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public MallUserInfo loginMa(LoginDto dto) {
        LambdaQueryWrapper<WxAppConfig> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(WxAppConfig::getAppId, dto.getAppId());
        WxAppConfig wxApp = wxAppConfigService.getOne(lambdaQueryWrapper);
        if (wxApp == null) {
            throw new JeecgBootException("没有找到此appid");
        }
        TenantContextHolder.setTenantId(wxApp.getTenantId());
        WxUser wxUser = null;
        //通过code获取微信用户信息
        try {
            WxMaInRedisConfigStorage configStorage = new WxMaInRedisConfigStorage(redisTemplate);
//            WxMaDefaultConfigImpl configStorage = new WxMaDefaultConfigImpl();
            configStorage.setAppid(wxApp.getAppId());
            configStorage.setSecret(wxApp.getAppSecret());
            WxMaService wxMaService = new WxMaServiceImpl();
            wxMaService.setWxMaConfig(configStorage);

            WxMaJscode2SessionResult jscode2session = wxMaService.jsCode2SessionInfo(dto.getJsCode());
            String openId = jscode2session.getOpenid();
            LambdaQueryWrapper<WxUser> lambdaQueryWrapper2 = new LambdaQueryWrapper<>();
            lambdaQueryWrapper2.eq(WxUser::getAppId, wxApp.getAppId());
            lambdaQueryWrapper2.eq(WxUser::getOpenId, openId);
            wxUser = wxUserService.getOne(lambdaQueryWrapper2);
            if (wxUser == null) {
                wxUser = new WxUser();
                wxUser.setOpenId(openId);
            }
            wxUser.setSessionKey(jscode2session.getSessionKey());
            wxUser.setUnionId(jscode2session.getUnionid());
        } catch (WxErrorException e) {
            e.printStackTrace();

            throw new JeecgBootException("小程序获取登录后的微信用户失败：" + e.getMessage());
        }
        System.out.println("【授权登录前】" + wxUser.toString());
        MallUserInfo userInfo;
        if (wxUser == null || StrUtil.isBlank(wxUser.getId())) {
            //新增微信用户
            wxUser.setAppId(wxApp.getAppId());
            wxUser.setTenantId(TenantContextHolder.getTenantId());
            wxUser.setAppType(wxApp.getAppType());
            wxUser.setNickName("微信用户");
            wxUserService.saveOrUpdate(wxUser);
        }
        System.out.println("【授权登录后】" + wxUser.toString());
        if (StrUtil.isNotBlank(wxUser.getUserId())) {
            userInfo = baseMapper.selectById(wxUser.getUserId());
        } else {
            userInfo = new MallUserInfo();
        }
        System.out.println("【用户信息】" + userInfo.toString());

        String token = UUID.randomUUID().toString();
        ThirdSession thirdSession = new ThirdSession();
        thirdSession.setTenantId(wxApp.getTenantId());
        thirdSession.setAppId(wxApp.getAppId());
        thirdSession.setSessionKey(wxUser.getSessionKey());
        thirdSession.setWxUserId(wxUser.getId());
        thirdSession.setOpenId(wxUser.getOpenId());
        thirdSession.setUserId(wxUser.getUserId());

        String key = CommonConstant.PREFIX_WX_APP_USER_TOKEN + token;

        // 设置token缓存有效时间
        redisUtil.set(key, com.alibaba.fastjson.JSON.toJSONString(thirdSession));
        redisUtil.expire(key, JwtUtil.EXPIRE_TIME * 24 * 30 / 1000);
        userInfo.setToken(token);
        return userInfo;
    }

    /**
     * 通过小程序授权手机号一键登录商城
     * @param dto
     * @return
     */
    public MallUserInfo loginByPhoneMa(WxOpenDataDto dto, String token) {
        ThirdSession thirdSession = ThirdSessionHolder.getThirdSession();
        String key = CommonConstant.PREFIX_WX_APP_USER_TOKEN + token;
        dto.setSessionKey(thirdSession.getSessionKey());
        dto.setAppId(thirdSession.getAppId());
        //解密获取手机号
        LambdaQueryWrapper<WxAppConfig> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(WxAppConfig::getAppId, dto.getAppId());
        WxAppConfig wxApp = wxAppConfigService.getOne(lambdaQueryWrapper);
        if (wxApp == null) {
            throw new JeecgBootException("没有找到此appid");
        }
        String phone = "";
        try {
            WxMaInRedisConfigStorage configStorage = new WxMaInRedisConfigStorage(redisTemplate);
            configStorage.setAppid(wxApp.getAppId());
            configStorage.setSecret(wxApp.getAppSecret());
            WxMaService wxMaService = new WxMaServiceImpl();
            wxMaService.setWxMaConfig(configStorage);

            WxMaUserService wxMaUserService = wxMaService.getUserService();
            WxMaPhoneNumberInfo wxMaPhoneNumberInfo = wxMaUserService.getPhoneNoInfo(dto.getSessionKey(), dto.getEncryptedData(), dto.getIv());
            phone = wxMaPhoneNumberInfo.getPhoneNumber();
        } catch (Exception e) {
            e.printStackTrace();
            throw new JeecgBootException("微信小程序授权拉取手机号码：" + e.getMessage());
        }
        //通过手机号登录
        MallUserInfo userInfo = loginByMobileWx(thirdSession, phone, key);
        return userInfo;
    }


    @Transactional(rollbackFor = Exception.class)
    public MallUserInfo loginByMobileWx(ThirdSession thirdSession, String mobile, String key) {
        //先查询该手机号是不是商城用户
        MallUserInfo userInfo = baseMapper.selectOne(Wrappers.<MallUserInfo>lambdaQuery()
                .eq(MallUserInfo::getMobile, mobile));
        if (userInfo == null) {//不是商城用户，则新增
            userInfo = new MallUserInfo();
            userInfo.setTenantId(TenantContextHolder.getTenantId());
            userInfo.setCreateTime(DateTime.now());
            userInfo.setUpdateTime(DateTime.now());
        }
        //先获取微信用户信息
        WxUser wxUser = wxUserService.getById(thirdSession.getWxUserId());
        //新增商城用户
        if (ObjectUtils.isEmpty(userInfo.getAppType())) {
            userInfo.setAppType(1);
        }
        if (StrUtil.isBlank(userInfo.getAppId())) {
            userInfo.setAppId(wxUser.getAppId());
        }
        if (StrUtil.isBlank(userInfo.getMobile())) {
            userInfo.setMobile(mobile);
        }
        if (StrUtil.isBlank(userInfo.getNickName())) {
            userInfo.setNickName(wxUser.getNickName());
        }
        if (StrUtil.isBlank(userInfo.getCity())) {
            userInfo.setCity(wxUser.getCity());
        }
        if (StrUtil.isBlank(userInfo.getCountry())) {
            userInfo.setCountry(wxUser.getCountry());
        }
        if (StrUtil.isBlank(userInfo.getAvatar())) {
            userInfo.setAvatar(wxUser.getAvatar());
        }
        if (StrUtil.isBlank(userInfo.getProvince())) {
            userInfo.setProvince(wxUser.getProvince());
        }
        if (ObjectUtils.isEmpty(userInfo.getGender())) {
            userInfo.setGender(wxUser.getGender());
        }
        //更新或新增商城用户
        this.saveOrUpdate(userInfo);
        String mallUserId = userInfo.getId();
        wxUser.setUserId(mallUserId);
        wxUser.setMobile(mobile);
        wxUserService.saveOrUpdate(wxUser);

        userInfo.setToken(StrUtil.removeAll(key, CommonConstant.PREFIX_WX_APP_USER_TOKEN));
        //更新微信用户

        //更新redis中的thirdSession
        thirdSession.setUserId(mallUserId);
        // 设置token缓存有效时间
        redisUtil.set(key, com.alibaba.fastjson.JSON.toJSONString(thirdSession));
        redisUtil.expire(key, JwtUtil.EXPIRE_TIME * 24 * 30 / 1000);
        return userInfo;
    }
}
